home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / circuits / irsim-9.000 / irsim-9 / src / irsim / config.c < prev    next >
C/C++ Source or Header  |  1993-01-15  |  14KB  |  531 lines

  1. /* 
  2.  *     ********************************************************************* 
  3.  *     * Copyright (C) 1988, 1990 Stanford University.                     * 
  4.  *     * Permission to use, copy, modify, and distribute this              * 
  5.  *     * software and its documentation for any purpose and without        * 
  6.  *     * fee is hereby granted, provided that the above copyright          * 
  7.  *     * notice appear in all copies.  Stanford University                 * 
  8.  *     * makes no representations about the suitability of this            * 
  9.  *     * software for any purpose.  It is provided "as is" without         * 
  10.  *     * express or implied warranty.  Export of this software outside     * 
  11.  *     * of the United States of America may require an export license.    * 
  12.  *     ********************************************************************* 
  13.  */
  14.  
  15. #include <stdio.h>
  16. #include "defs.h"
  17. #include "net.h"
  18. #include "globals.h"
  19.  
  20.  
  21. /*
  22.  * electrical parameters used for deriving capacitance info for charge
  23.  * sharing.  Default values aren't for any particular process, but are
  24.  * self-consistent.
  25.  *    Area capacitances are all in pfarads/sq-micron units.
  26.  *    Perimeter capacitances are all in pfarads/micron units.
  27.  */
  28. public    double  CM2A = .00000;    /* 2nd metal capacitance -- area */
  29. public    double  CM2P = .00000;    /* 2nd metal capacitance -- perimeter */
  30. public    double  CMA = .00003;    /* 1st metal capacitance -- area */
  31. public    double  CMP = .00000;    /* 1st metal capacitance -- perimeter */
  32. public    double  CPA = .00004;    /* poly capacitance -- area */
  33. public    double  CPP = .00000;    /* poly capacitance -- perimeter */
  34. public    double  CDA = .00010;    /* n-diffusion capacitance -- area */
  35. public    double  CDP = .00060;    /* n-diffusion capacitance -- perimeter */
  36. public    double  CPDA = .00010;    /* p-diffusion capacitance -- area */
  37. public    double  CPDP = .00060;    /* p-diffusion capacitance -- perimeter */
  38. public    double  CGA = .00040;    /* gate capacitance -- area */
  39.                 /* the following are computed from above */
  40. public    double    CTDW;        /* xtor diff-width capacitance -- perimeter */
  41. public    double    CTDE;        /* xtor diff-extension cap. -- perimeter */
  42. public    double    CTGA;        /* xtor gate capacitance -- area */
  43.  
  44. public    double  LAMBDA = 2.5;      /* microns/lambda */
  45. public    double  LAMBDA2 = 6.25;      /* LAMBDA**2 */
  46. public    long    LAMBDACM = 250;      /* centi-microns/lambda */
  47. public    double  LOWTHRESH = 0.3;  /* low voltage threshold, normalized units */
  48. public    double  HIGHTHRESH = 0.8; /* high voltage threshold,normalized units */
  49. public    double  DIFFEXT = 0;      /* width of source/drain diffusion */
  50.  
  51. public    int    config_flags = 0;
  52.  
  53. #define    CM_M    (100.0)        /* centimicrons per micron */
  54.  
  55. /* values of config_flags */
  56.  
  57.  
  58. public
  59. #define    TDIFFCAP    0x1    /* set if DIFFPERIM or DIFFEXTF are true    */
  60.  
  61. #define    CNTPULLUP    0x2    /* set if capacitance from gate of pullup   */
  62.                 /* should be included.                */
  63.  
  64. #define    DIFFPERIM    0x4    /* set if diffusion perimeter does not         */
  65.                 /* include sources/drains of transistors.   */
  66.  
  67. #define    SUBPAREA    0x8    /* set if poly over xistor doesn't make a   */
  68.                 /* capacitor.                    */
  69.  
  70. #define    DIFFEXTF    0x10    /* set if we should add capacitance due to  */
  71.                 /* diffusion-extension of source/drain.        */
  72.  
  73.  
  74. typedef struct    /* table translating parameters to its associated names */
  75.   {
  76.     char      *name;
  77.     int       flag;
  78.     double    *dptr;
  79.   } pTable;
  80.  
  81. private    pTable  parms[] = 
  82.   {
  83.     "capm2a",        0x0,    &CM2A,
  84.     "capm2p",        0x0,    &CM2P,
  85.     "capma",        0x0,    &CMA,
  86.     "capmp",        0x0,    &CMP,
  87.     "cappa",        0x0,    &CPA,
  88.     "cappp",        0x0,    &CPP,
  89.     "capda",        0x0,    &CDA,
  90.     "capdp",        0x0,    &CDP,
  91.     "cappda",        0x0,    &CPDA,
  92.     "cappdp",        0x0,    &CPDP,
  93.     "capga",        0x0,    &CGA,
  94.     "lambda",        0x0,    &LAMBDA,
  95.     "lowthresh",    0x0,    &LOWTHRESH,
  96.     "highthresh",   0x0,    &HIGHTHRESH,
  97.     "diffperim",    DIFFPERIM,    NULL,
  98.     "cntpullup",    CNTPULLUP,    NULL,
  99.     "subparea",        SUBPAREA,    NULL,
  100.     "diffext",        DIFFEXTF,    &DIFFEXT,
  101.     NULL,        0x0,    NULL
  102.   };
  103.  
  104.  
  105. #define    LSIZE        500    /* max size of parameter file input line */
  106. #define    MAXARGS        10    /* max number of arguments in line */
  107.  
  108. private    int     lineno;        /* current line number */
  109. private    char    *currfile;    /* current input file */
  110. private    int     nerrs = 0;    /* errors found in config file */
  111. private    int     maxerr;
  112. private    char    *ttype_drop[ NTTYPES ];
  113.  
  114.     /* forward references */
  115. private    void    insert();
  116.  
  117.  
  118. private int ParseLine( line, args )
  119.   register char  *line;
  120.   char           **args;
  121.   {
  122.     register char  c;
  123.     int            ac = 0;
  124.  
  125.     for( ; ; )
  126.       {
  127.     while( (c = *line) <= ' ' and c != '\0' )
  128.         line++;
  129.     if( c == '\0' or c == ';' )
  130.         break;
  131.     *args++ = line;
  132.     ac++;
  133.     while( (c = *line) > ' ' and c != ';' )
  134.         line++;
  135.     *line = '\0';
  136.     if( c == '\0' or c == ';' )
  137.         break;
  138.     line++;
  139.       }
  140.     *line = '\0';
  141.     *args = NULL;
  142.     return( ac );
  143.   }
  144.  
  145.  
  146. public void config( cname )
  147.   char  *cname;
  148.   {
  149.     register pTable  *p;
  150.     FILE             *cfile;
  151.     char             prm_file[256];
  152.     char             line[LSIZE];
  153.     char             *targv[MAXARGS];
  154.     char             tmpbuff[NTTYPES * 22];
  155.     int              targc;
  156.  
  157.     for( targc = 0; targc < NTTYPES; targc++ )
  158.       {
  159.     ttype_drop[ targc ] = &tmpbuff[ targc * 22 ];
  160.     (void) sprintf( ttype_drop[ targc ], "%s-with-drop", ttype[ targc ] );
  161.       }
  162.  
  163.     if( *cname != '/' )        /* not full path specified */
  164.       {
  165.     Fstat  *stat;
  166.     
  167.     stat = FileStatus( cname );
  168.     if( not stat->read )
  169.       {
  170.         (void) sprintf( prm_file, "%s/%s", cad_lib, cname );
  171.         stat = FileStatus( prm_file );
  172.         if( stat->read )
  173.             cname = prm_file;
  174.         else
  175.           {
  176.         (void) strcat( prm_file, ".prm" );
  177.         stat = FileStatus( prm_file );
  178.         if( stat->read )
  179.             cname = prm_file;
  180.           }
  181.       }
  182.       }
  183.     currfile = cname;
  184.  
  185.     lineno = 0;
  186.     if( (cfile = fopen( cname, "r" )) == NULL )
  187.       {
  188.     lprintf(stderr,"can't open electrical parameters file <%s>\n", cname);
  189.     exit( 1 );
  190.       }
  191.  
  192.     *line = '\0';
  193.     (void) fgetline( line, LSIZE, cfile );
  194.     if( strncmp( line, "; configuration file", 20 ) )
  195.       {
  196.     rewind( cfile );
  197.     maxerr = 1;
  198.       }
  199.     else
  200.     maxerr = 15;
  201.  
  202.     while( fgetline( line, LSIZE, cfile ) != NULL )
  203.       {
  204.     lineno++;
  205.     targc = ParseLine( line, targv );
  206.     if( targc == 0 )
  207.         continue;
  208.     if( str_eql( "resistance", targv[0] ) == 0 )
  209.       {
  210.         if( targc >= 6 )
  211.         insert( targv[1], targv[2], targv[3], targv[4], targv[5] );
  212.         else
  213.           {
  214.         error( currfile, lineno, "syntax error in resistance spec\n" );
  215.         nerrs++;
  216.           }
  217.         continue;
  218.       }
  219.     else
  220.       {
  221.         for( p = parms; p->name != NULL; p++ )
  222.           {
  223.         if( str_eql( p->name, targv[0] ) == 0 )
  224.           {
  225.             if( p->dptr != NULL )
  226.             *(p->dptr) = atof( targv[1] );
  227.             if( p->flag != 0 and atoi( targv[1] ) != 0 )
  228.             config_flags |= p->flag;
  229.             break;
  230.           }
  231.           }
  232.         if( p->name == NULL )
  233.           {
  234.         error( currfile, lineno,
  235.           "unknown electrical parameter: (%s)\n", targv[0] );
  236.         nerrs++;
  237.           }
  238.       }
  239.     if( nerrs >= maxerr )
  240.       {
  241.         if( maxerr == 1 )
  242.         lprintf( stderr,
  243.           "I think %s is not an electrical parameters file\n", cname );
  244.         else
  245.         lprintf( stderr, "Too many errors in '%s'\n", cname );
  246.         exit( 1 );
  247.       }
  248.       }
  249.     LAMBDA2 = LAMBDA * LAMBDA;
  250.     LAMBDACM = LAMBDA * CM_M;
  251.     CTGA = ( (config_flags & SUBPAREA) ? (CGA - CPA) : CGA ) / (CM_M * CM_M);
  252.     switch( config_flags & (DIFFEXTF | DIFFPERIM) )
  253.       {
  254.     case 0 :
  255.         CTDE = CTDW = 0.0;    break;
  256.     case DIFFPERIM :
  257.         config_flags |= TDIFFCAP;
  258.         CTDE = 0.0;
  259.         CTDW = -(CDP / CM_M);
  260.         break;
  261.     case DIFFEXTF :
  262.         config_flags |= TDIFFCAP;
  263.         CTDE = (2 * DIFFEXT * LAMBDA * CDP);
  264.         CTDW = (CDP + DIFFEXT * LAMBDA * CDA) / CM_M;
  265.         break;
  266.     case (DIFFEXTF | DIFFPERIM) :
  267.         config_flags |= TDIFFCAP;
  268.         CTDE = (2 * DIFFEXT * LAMBDA * CDP);
  269.         CTDW = (DIFFEXT * LAMBDA * CDA) / CM_M;
  270.         break;
  271.       }
  272.  
  273.     if( config_flags & CNTPULLUP )
  274.     lprintf( stderr, "warning: cntpullup is not supported\n" );
  275.  
  276.     (void) fclose( cfile );
  277.   }
  278.  
  279.  
  280. /*
  281.  * info on resistance vs. width and length are stored first sorted by
  282.  * width, then by length.
  283.  */
  284. struct length
  285.   {
  286.     struct length    *next;    /* next element with same width */
  287.     long             l;        /* length of this channel in centimicrons */
  288.     double           r;        /* equivalent resistance/square */
  289.   };
  290.  
  291. struct width
  292.   {
  293.     struct width     *next;    /* next width */
  294.     long             w;        /* width of this channel in centimicrons */
  295.     struct length    *list;    /* list of length structures */
  296.   } *resistances[ R_TYPES ][ NTTYPES ];
  297.  
  298.  
  299. /* linear interpolation, assume that x1 < x <= x2 */
  300. #define    interp( x, x1, y1, x2, y2 )  \
  301.   ( (((double) (x - x1)) / ((double) (x2 - x1))) * (y2 - y1) + y1 )
  302.  
  303.  
  304. /*
  305.  * given a list of length structures, sorted by incresing length return
  306.  * resistance of given channel.  If no exact match, return result of
  307.  * linear interpolation using two closest channels.
  308.  */
  309. private double lresist( list, l, size )
  310.   register struct length  *list;
  311.   long                    l;
  312.   double                  size;
  313.   {
  314.     register struct length  *p, *q;
  315.  
  316.     for( p = list, q = NULL; p != NULL; q = p, p = p->next )
  317.       {
  318.     if( p->l == l or( p->l > l and q == NULL ) )
  319.         return( p->r * size );
  320.     if( p->l > l )
  321.         return( size * interp( l, q->l, q->r, p->l, p->r ) );
  322.       }
  323.     if( q != NULL )
  324.     return( q->r *size );
  325.     return( 1E4 * size );
  326.   }
  327.  
  328.  
  329. /*
  330.  * given a pointer to the width structures for a particular type of
  331.  * channel compute the resistance for the specified channel.
  332.  */
  333. private double wresist( list, w, l )
  334.   register struct width  *list;
  335.   long                   w, l;
  336.   {
  337.     register struct width  *p, *q;
  338.     double                 size = ((double) l) / ((double) w);
  339.     double                 temp;
  340.  
  341.     for( p = list, q = NULL; p != NULL; q = p, p = p->next )
  342.       {
  343.     if( p->w == w or( p->w > w and q == NULL ) )
  344.         return( lresist( p->list, l, size ) );
  345.     if( p->w > w )
  346.       {
  347.         temp = lresist( q->list, l, size );
  348.         return( interp( w, q->w, temp, p->w, lresist( p->list, l, size ) ) );
  349.       }
  350.       }
  351.     if( q != NULL )
  352.     return( lresist( q->list, l, size ) );
  353.     return( 1E4 * size );
  354.   }
  355.  
  356. typedef struct ResEntry  *resptr;
  357.  
  358. typedef struct ResEntry
  359.   {
  360.     resptr    r_next;
  361.     Resists   r;
  362.   } ResEntry;
  363.  
  364. #define    RES_TAB_SIZE    67
  365.  
  366. /*
  367.  * Compute equivalent resistance given width, length and type of transistor.
  368.  * for all contexts (STATIC, DYNHIGH, DYNLOW).  Place the result on the
  369.  * transistor 
  370.  */
  371. public Resists *requiv( type, width, length )
  372.   int   type;
  373.   long  width, length;
  374.   {
  375.     static resptr    *res_htab[ NTTYPES ];
  376.     static resptr    freeResist;
  377.     resptr           *rtab;
  378.     register resptr  r;
  379.     unsigned         n;
  380.  
  381.     type = BASETYPE( type );
  382.  
  383.     rtab = res_htab[ type ];
  384.     if( rtab == NULL )
  385.       {
  386.     rtab = (resptr *) Valloc( RES_TAB_SIZE * sizeof( resptr * ), 1 );
  387.     for( n = 0; n < RES_TAB_SIZE; rtab[ n++ ] = NULL );
  388.     res_htab[ type ] = rtab;
  389.       }
  390.     n = ((unsigned) (length * 110133 + width)) % RES_TAB_SIZE;
  391.     for( r = rtab[ n ]; r != NULL; r = r->r_next )
  392.       {
  393.     if( r->r.length == length and r->r.width == width ) return( &r->r );
  394.       }
  395.  
  396.     if( (r = freeResist) == NULL )
  397.     r = (resptr) MallocList( sizeof( ResEntry ), 1 );
  398.     freeResist = r->r_next;
  399.     r->r_next = rtab[n];
  400.     rtab[n] = r;
  401.  
  402.     r->r.length = length;
  403.     r->r.width = width;
  404.  
  405.     if( type == RESIST )
  406.       {
  407.     r->r.dynlow = r->r.dynhigh = r->r.rstatic = (float) length / LAMBDACM;
  408.       }
  409.     else
  410.       {
  411.     r->r.rstatic = wresist( resistances[ STATIC ][type], width, length );
  412.     r->r.dynlow = wresist( resistances[ DYNLOW ][type], width, length );
  413.     r->r.dynhigh = wresist( resistances[ DYNHIGH ][type], width, length );
  414.       }
  415.     return( &r->r );
  416.   }
  417.  
  418.  
  419. private void linsert( list, l, resist )
  420.   register struct length  **list;
  421.   long                    l;
  422.   double                  resist;
  423.   {
  424.     register struct length  *p, *q, *lnew;
  425.  
  426.     for( p = *list, q = NULL; p != NULL; q = p, p = p->next )
  427.       {
  428.     if( p->l == l )
  429.       {
  430.         p->r = resist;
  431.         return;
  432.       }
  433.     if( p->l > l )
  434.         break;
  435.       }
  436.     lnew = (struct length *) Valloc( sizeof( struct length ), 1 );
  437.     lnew->next = p;
  438.     lnew->l = l;
  439.     lnew->r = resist;
  440.     if( q == NULL )
  441.     *list = lnew;
  442.     else
  443.     q->next = lnew;
  444.   }
  445.  
  446.  
  447. /* add a new data point to the interpolation array */
  448. private void winsert( list, w, l, resist )
  449.   register struct width  **list;
  450.   long                   w, l;
  451.   double                 resist;
  452.   {
  453.     register struct width   *p, *q, *wnew;
  454.     register struct length  *lnew;
  455.  
  456.     for( p = *list, q = NULL; p != NULL; q = p, p = p->next )
  457.       {
  458.     if( p->w == w )
  459.       {
  460.         linsert( &p->list, l, resist );
  461.         return;
  462.       }
  463.     if( p->w > w )
  464.         break;
  465.       }
  466.     wnew = (struct width *) Valloc( sizeof( struct width ), 1 );
  467.     lnew = (struct length *) Valloc( sizeof( struct length ), 1 );
  468.     wnew->next = p;
  469.     wnew->list = lnew;
  470.     wnew->w = w;
  471.     if( q == NULL )
  472.     *list = wnew;
  473.     else
  474.     q->next = wnew;
  475.     lnew->next = NULL;
  476.     lnew->l = l;
  477.     lnew->r = resist;
  478.   }
  479.  
  480.  
  481. /* interpret resistance specification command */
  482. private void insert( type, context, w, l, r )
  483.   char  *type, *context, *w, *l, *r;
  484.   {
  485.     register int  c, t;
  486.     long          width, length;
  487.     double        resist;
  488.  
  489.     width = atof( w ) * CM_M;
  490.     length = atof( l ) * CM_M;
  491.     resist = atof( r );
  492.     if( width <= 0 or length <= 0 or resist <= 0 )
  493.       {
  494.     error( currfile, lineno, "bad w, l, or r in config file\n" );
  495.     nerrs++;
  496.     return;
  497.       }
  498.  
  499.     if( str_eql( context, "static" ) == 0 )
  500.     c = STATIC;
  501.     else if( str_eql( context, "dynamic-high" ) == 0 )
  502.     c = DYNHIGH;
  503.     else if( str_eql( context, "dynamic-low" ) == 0 )
  504.     c = DYNLOW;
  505.     else if( str_eql( context, "power" ) == 0 )
  506.     c = POWER;
  507.     else
  508.       {
  509.     error( currfile, lineno, "bad resistance context in config file\n" );
  510.     nerrs++;
  511.     return;
  512.       }
  513.  
  514.     for( t = 0; t < NTTYPES; t++ )
  515.       {
  516.     if( str_eql( ttype[t], type ) == 0 )
  517.       {
  518.         if( c == POWER )
  519.         return;
  520.         winsert( &resistances[c][t], width, length, resist*width/length );
  521.         return;
  522.       }
  523.     else if( str_eql( ttype_drop[t], type ) == 0 )
  524.         return;
  525.       }
  526.  
  527.     error( currfile, lineno, "bad resistance transistor type\n" );
  528.     nerrs++;
  529.   }
  530.  
  531.